package com.strato.profiled.annotation.v1_0_0.advice;

import java.lang.reflect.Method;

import org.perf4j.StopWatch;

import com.strato.annotation.osgi.v1_0_0.service.OsgiService;
import com.strato.base.aop.v1_0_0.Invocation;
import com.strato.base.aop.v1_0_0.advice.Advice;
import com.strato.profiled.annotation.v1_0_0.annotation.Profiled;

@OsgiService(id="profiledAdvice")
public class ProfiledAdvice implements Advice {

	@Override
	public int getOrder() {
		return 1000;
	}

	@Override
	public boolean supports(Object o, Method method, Object[] args) {
		return method.isAnnotationPresent(Profiled.class);
	}

	@Override
	public Object proceed(Invocation invocation) throws Throwable{
		Profiled profiled=invocation.getMethod().getAnnotation(Profiled.class);
		String tag=profiled.tag();
		if(Profiled.AUTO_GENERATE_TAG.equals(tag)){
			tag=calcSignature(invocation);
		}
		StopWatch sw=new StopWatch(tag);
		try{
			sw.start();
			return invocation.proceed();
		}finally{
			sw.stop();
		}
	}

	private String calcSignature(Invocation invocation) {
		Object o = invocation.getObject();
		Method method = invocation.getMethod();
		StringBuffer buf=new StringBuffer();
		buf.append(o.getClass().getName());
		buf.append(".");
		buf.append(method.getName());
		buf.append("(");
		Class<?>[] pts = method.getParameterTypes();
		if(pts!=null){
			for(Class<?> pt:pts){
				buf.append(pt.getSimpleName()).append(",");
			}
		}
		buf.append(")");
		return buf.toString();
	}

}
